package com.yqg.education.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang.StringUtils;

import javax.imageio.ImageIO;
import javax.swing.filechooser.FileSystemView;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Log4j2
public class QRCodeUtil {

    private static final int CODE_WIDTH = 480; // 二维码宽度
    private static final int CODE_HEIGHT = 400; // 二维码高度
    private static final int TEXT_HEIGHT = 60; // 底部文字高度
    private static final int FRONT_COLOR = 0x000000; // 前景色
    private static final int BACKGROUND_COLOR = 0xFFFFFF; // 背景色

    public static String createCodeToFile(String content, File codeImgFileSaveDir, String fileName, String bottomText) {
        try {
            if (StringUtils.isBlank(content) || StringUtils.isBlank(fileName)) {
                return null;
            }
            content = content.trim();
            if (codeImgFileSaveDir == null || codeImgFileSaveDir.isFile()) {
                codeImgFileSaveDir = FileSystemView.getFileSystemView().getHomeDirectory();
            }
            if (!codeImgFileSaveDir.exists()) {
                codeImgFileSaveDir.mkdirs();
            }

            // 核心代码 - 生成二维码并添加文字
            BufferedImage qrCodeImage = getBufferedImage(content);
            BufferedImage finalImage = addTextToImage(qrCodeImage, bottomText);

            File codeImgFile = new File(codeImgFileSaveDir, fileName);
            ImageIO.write(finalImage, "png", codeImgFile);

            log.info("二维码图片生成成功：" + codeImgFile.getPath());
            return codeImgFile.getPath().replace("\\", "/");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static BufferedImage getBufferedImage(String content) throws WriterException {
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        hints.put(EncodeHintType.MARGIN, 1);

        MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
        BitMatrix bitMatrix = multiFormatWriter.encode(
                new String(content.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8),
                BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_HEIGHT, hints);

        BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR);
        for (int x = 0; x < CODE_WIDTH; x++) {
            for (int y = 0; y < CODE_HEIGHT; y++) {
                bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
            }
        }
        return bufferedImage;
    }

    private static BufferedImage addTextToImage(BufferedImage qrCodeImage, String text) {
        int width = qrCodeImage.getWidth();
        int height = qrCodeImage.getHeight() + TEXT_HEIGHT;

        BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = newImage.createGraphics();

        // 设置背景为白色
        graphics.setColor(Color.WHITE);
        graphics.fillRect(0, 0, width, height);

        // 绘制二维码
        graphics.drawImage(qrCodeImage, 0, 0, null);

        // 设置文字颜色和字体
        graphics.setColor(Color.BLACK);
        graphics.setFont(new Font("微软雅黑", Font.PLAIN, 30));

        // 计算文字位置
        FontMetrics fontMetrics = graphics.getFontMetrics();
        int textWidth = fontMetrics.stringWidth(text);
        int x = (width - textWidth) / 2;
        int y = qrCodeImage.getHeight() + (TEXT_HEIGHT - fontMetrics.getHeight()) / 2 + fontMetrics.getAscent();

        // 绘制文字
        graphics.drawString(text, x, y);

        graphics.dispose();
        return newImage;
    }
}
